# Лекция: Тип Optional в Java

Optional в Java - это контейнерный объект, который может содержать или не содержать значение. Он используется для представления отсутствующих значений без использования null.

## Создание Optional

Optional можно создать с помощью методов `Optional.of()`, `Optional.ofNullable()` и `Optional.empty()`.

```java
Optional<String> optional1 = Optional.of("Hello, world!"); // содержит значение
Optional<String> optional2 = Optional.ofNullable(null); // может содержать значение или быть пустым
Optional<String> optional3 = Optional.empty(); // пустой Optional
```

## Использование Optional

С Optional можно работать с помощью методов `isPresent()`, `get()`, `orElse()`, `orElseGet()`, `orElseThrow()` и других.

```java
if (optional1.isPresent()) {
    String value = optional1.get();
}

String value2 = optional2.orElse("Default value");

String value3 = optional3.orElseGet(() -> "Default value");

String value4 = optional3.orElseThrow(() -> new RuntimeException("Value is absent"));
```

---

# Практические задания

1. **Создайте Optional, который содержит строку "Hello, world!", и выведите его значение.** (Сложность: 1/5)
```java
Optional<String> optional = Optional.of("Hello, world!");
if (optional.isPresent()) {
    System.out.println(optional.get());
}
```

2. **Создайте пустой Optional, и верните "Default value", если значение отсутствует.** (Сложность: 1/5)
```java
Optional<String> optional = Optional.empty();
String value = optional.orElse("Default value");
System.out.println(value); // выводит "Default value"
```

3. **Создайте метод `findUserById`, который возвращает Optional пользователя. Если пользователь найден, возвращается его имя, в противном случае возвращается пустой Optional.** (Сложность: 2/5)
```java
Optional<String> findUserById(int id) {
    // предположим, что это поиск в базе данных
    if (id == 123) {
        return Optional.of("John Doe");
    } else {
        return Optional.empty();
    }
}

Optional<String> user = findUserById(123);
System.out.println(user.orElse("User not found")); // выводит "John Doe"

Optional<String> user2 = findUserById(456);
System.out.println(user2.orElse("User not found")); // выводит "User not found"
```

4. **Создайте метод `findProductById`, который возвращает Optional продукта. Если продукт найден, возвращается его название, в противном случае выбрасывается исключение.** (Сложность: 3/5)
```java
Optional<String> findProductById(int id) {
    // предположим, что это поиск в базе данных
    if (id == 123) {
        return Optional.of("Apple");
    } else {
        return Optional.empty();
    }
}

String product = findProductById(123).orElseThrow(() -> new RuntimeException("Product not found"));
System.out.println(product); // выводит "Apple"

try {
    String product2 = findProductById(456).orElseThrow(() -> new RuntimeException("Product not found"));
    System.out.println(product2);
} catch (RuntimeException e) {
    System.out.println(e.getMessage()); // выводит "Product not found"
}
```

5. **Создайте метод `loadData`, который возвращает Optional данных. Если данные загружены, возвращается их размер, в противном случае возвращается размер по умолчанию.** (Сложность: 3/5)
```java
Optional<String> loadData() {
    // предположим, что это загрузка данных из файла или сети
    return Math.random() > 0.5 ? Optional.of("Data") : Optional.empty();
}

int size = loadData().map(String::length).orElse(0);
System.out.println(size); // выводит 4 или 0
```